<?php
/***********************************************************************
 * @package    	IvanEngine
 * @subpackage 	Core
 * @author     	Ivan <ivanzx@msn.com>
 * @created    	2010-05-17
 ***********************************************************************/
if(defined("IVANENGINE_CORE_VALIDATOR_AND"))
	die("Redefinition macro in :".__FILE__."(".__LINE__.")");
define("IVANENGINE_CORE_VALIDATOR_AND", true);

require_once (dirname(__FILE__).'/ValidatorBase.php');
require_once (dirname(__FILE__).'/../ExceptionValidatorMap.php');

class CValidatorAnd extends CValidatorBase
{
	protected
    	$m_validators = array();

  	/**
   	* Constructor.
   	*
   	* The first argument can be:
   	*  * null
   	*  * a sfValidatorBase instance
   	*  * an array of sfValidatorBase instances
   	*
   	* @param mixed $m_validators Initial m_validators
   	* @param array $options    An array of options
   	* @param array $messages   An array of error messages
   	*/
  	public function __construct($m_validators = null, $options = array(), $messages = array())
  	{
    	if ($m_validators instanceof CValidatorBase)
    	{
      		$this->AddValidator($m_validators);
    	}
    	else if (is_array($m_validators))
    	{
      		foreach ($m_validators as $validator)
      		{
        		$this->AddValidator($validator);
      		}
    	}
    	else if (!is_null($m_validators))
    	{
      	throw new CExceptionInvalidArgument('ValidatorAnd constructor takes a sfValidatorBase object, or a sfValidatorBase array.');
    	}
    
    	parent::__construct($options, $messages);
  	}

  	protected function Initialize($options = array(), $messages = array())
  	{
  		parent::Initialize($options, $messages);
  		
    	$this->AddOption('halt_on_error', false);
    	$this->SetMessage('invalid', null);
  	}

  	/**
   	* Adds a validator.
   	*
   	* @param sfValidatorBase $validator  A sfValidatorBase instance
   	*/
  	public function AddValidator(sfValidatorBase $validator)
  	{
    	$this->m_validators[] = $validator;
  	}

  	/**
   	* Returns an array of the m_validators.
   	*
   	* @return array An array of sfValidatorBase instances
   	*/
  	public function GetValidators()
  	{
    	return $this->m_validators;
  	}

  	/**
   	* @see sfValidatorBase
   	*/
  	protected function DoVerify($value)
  	{
    	$clean = $value;
    	$errors = array();
    	foreach ($this->m_validators as $validator)
    	{
      		try
      		{
        		$clean = $validator->Verify($clean);
      		}
      		catch (CExceptionValidator $e)
      		{
       			$errors[] = $e;

       			if ($this->GetOption('halt_on_error'))
        		{
          			break;
        		}
      		}
    	}

    	if (count($errors))
    	{
      		if ($this->GetMessage('invalid'))
      		{
        		throw new CExceptionValidator($this, 'invalid', array('value' => $value));
      		}

      		throw new CExceptionValidatorMap($this, $errors);
    	}

    	return $clean;
  	}

  /**
   * @see sfValidatorBase
   */
  public function AsString($indent = 0)
  {
    $validators = '';
    for ($i = 0, $max = count($this->m_validators); $i < $max; $i++)
    {
      $validators .= "\n".$this->m_validators[$i]->asString($indent + 2)."\n";

      if ($i < $max - 1)
      {
        $validators .= str_repeat(' ', $indent + 2).'and';
      }

      if ($i == $max - 2)
      {
        $options = $this->getOptionsWithoutDefaults();
        $messages = $this->getMessagesWithoutDefaults();

        if ($options || $messages)
        {
          $validators .= sprintf('(%s%s)',
            $options ? $options : ($messages ? '{}' : ''),
            $messages ? ', '.$messages : ''
          );
        }
      }
    }

    return sprintf("%s(%s%s)", str_repeat(' ', $indent), $validators, str_repeat(' ', $indent));
  }
}

?>